package com.bestcem.xm.member.dao.impl.mysql;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bestcem.xm.common.core.sql.SQLConditionCompiler;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.common.core.uitls.StringUtil;
import com.bestcem.xm.label.grpc.service.param.LabelValueIdParam;
import com.bestcem.xm.member.dao.MemberDao;
import com.bestcem.xm.member.dao.mapper.MemberMapper;
import com.bestcem.xm.member.entity.mysql.MemberEntity;
import com.bestcem.xm.member.entity.pojo.ExtendFieldDO;
import com.bestcem.xm.member.entity.pojo.ExtendFieldEnumItemDO;
import com.bestcem.xm.member.entity.pojo.MemberDO;
import com.bestcem.xm.member.enums.DeliveryTypeEnum;
import com.bestcem.xm.member.enums.MemberStatusEnum;
import com.bestcem.xm.member.enums.MemberTypeEnum;
import com.bestcem.xm.member.grpc.service.param.member.MemberQuery;
import com.bestcem.xm.member.service.param.DeliveryMembersDynamicSql;
import com.bestcem.xm.member.service.param.FuzzyMemberDynamicSql;
import com.bestcem.xm.member.service.param.SelectMemberDynamicSql;
import com.bestcem.xm.member.service.param.UpdateMemberGroupDynamicSql;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 联系人持久层
 *
 * @author yf.wang <yf.wang@idiaoyan.com>
 * @version V1.0
 * @date 2021/7/16
 */

@Repository
public class MemberDaoImpl implements MemberDao {
    private SQLConditionCompiler sqlConditionCompiler = SQLConditionCompiler.newInstance();

    @Resource
    private MemberMapper memberMapper;

    @Override
    public List<MemberDO> listOrgMembers(String orgId, Integer memberType, Integer offset, Integer size) {
        List<MemberEntity> entities = memberMapper.findPageByOrgIdAndMemberType(orgId, memberType, offset, size);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public Long countOrgMembers(String orgId, Integer memberType) {
        return memberMapper.countByOrgIAndMemberTypeAndStatus(orgId, memberType, MemberStatusEnum.ACTIVATED.getIndex());
    }

    @Override
    public List<MemberDO> list(String orgId, List<String> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return new ArrayList<>();
        }
        List<MemberEntity> memberEntities = memberMapper.findByIds(ids);
        return memberEntities.stream().filter(m -> orgId.equals(m.getOrgId())).map(this::convert).collect(Collectors.toList());
    }

    @Override
    public List<MemberDO> listMemberByPeriod(String orgId, Date startCreateTime, Date endCreateTime, Date startUpdateTime, Date endUpdateTime) {
        return null;
    }

    @Override
    public List<MemberDO> listMembersByPhones(String orgId, Integer type, Collection<String> phones) {
        if (CollectionUtils.isEmpty(phones)) {
            return new ArrayList<>();
        }

        List<MemberEntity> entities = memberMapper.listMembersByPhones(orgId, type, phones);
        return entities.stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public List<MemberDO> listMembersByEmails(String orgId, Integer type, Collection<String> emails) {
        if (CollectionUtils.isEmpty(emails)) {
            return new ArrayList<>();
        }

        List<MemberEntity> entities = memberMapper.listMembersByPhones(orgId, type, emails);
        return entities.stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public Long countIndividualMember(String orgId) {
        // return memberMapper.countByOrgIAndMemberType(orgId, MemberTypeEnum.INDIVIDUAL.getIndex());
        return memberMapper.countByOrgIAndMemberTypeAndStatusAndSourceNe(orgId, MemberTypeEnum.INDIVIDUAL.getIndex(), MemberStatusEnum.ACTIVATED.getIndex(), "sample");
    }

    @Override
    public Integer countByOrgIdAndInstituteNameAndNotEqualStatus(String orgId, String instituteName, int status) {
        return memberMapper.countByOrgIdAndInstituteNameAndNotEqualStatus(orgId, instituteName, status);
    }

    @Override
    public long updateStatusByIds(List<String> ids, int status) {
        return memberMapper.updateStatusByIds(ids, status);
    }

    @Override
    public List<Boolean> batchUpsertOpenPlatformMembers(List<MemberDO> members) {
        List<MemberEntity> createMembers = new ArrayList<>();
        List<MemberEntity> updateMembers = new ArrayList<>();

        for (MemberDO memberDO : members) {
            MemberEntity member = this.convert(memberDO);
            if (StringUtils.hasText(memberDO.getId())) {
                updateMembers.add(member);
            } else {
                // 添加id
                member.setId(StringUtil.getId());
                memberDO.setId(member.getId());
                createMembers.add(member);
            }
        }

        if (!CollectionUtils.isEmpty(createMembers)) {
            memberMapper.batchInsertMembers(createMembers);
        }

        if (!CollectionUtils.isEmpty(updateMembers)) {
            memberMapper.batchUpdateOpenPlatformMembers(updateMembers);
        }

        return new ArrayList<>();
    }

    @Override
    public MemberDO findUndeletedMemberByEmail(String orgId, Integer memberType, String email) {
        MemberEntity entity = memberMapper.findByOrgIdAndFieldAndAttributeAndStatusNe(orgId, "email", email, memberType, MemberStatusEnum.SOFT_DELETE.getIndex());
        return MemberDO.toDo(entity);
    }

    @Override
    public MemberDO findUndeletedMemberByPhone(String orgId, Integer memberType, String phone) {
        MemberEntity entity = memberMapper.findByOrgIdAndFieldAndAttributeAndStatusNe(orgId, "phone", phone, memberType, MemberStatusEnum.SOFT_DELETE.getIndex());
        return MemberDO.toDo(entity);
    }

    @Override
    public MemberDO findByAppIdAndOpenId(String orgId, Integer memberType, String appId, String openId) {
        MemberEntity entity = memberMapper.findByAppIdAndOpenId(orgId, memberType, appId, openId);
        return MemberDO.toDo(entity);
    }

    @Override
    public List<MemberDO> listByAppIdAndOpenId(String orgId, Integer memberType, String appId, String openId) {
        List<MemberEntity> entities = memberMapper.listByAppIdAndOpenId(orgId, memberType, appId, openId);
        return entities.stream().map(MemberDO::toDo).collect(Collectors.toList());
    }

    @Override
    public List<MemberDO> findByOrgIdAndMobileAndEmailAndAliPayUserIdAndOpenidAndAttribute(String orgId, String mobile,
                                                                                           String email,
                                                                                           String aliPayUserId,
                                                                                           String openId,
                                                                                           String outNo, Integer mType,
                                                                                           List<Integer> statusList) {
        List<MemberEntity> entities = memberMapper
                .findByOrgIdAndMobileAndEmailAndAliPayUserIdAndOpenidAndAttribute(orgId, mobile, email, aliPayUserId,
                        openId, outNo, mType, statusList);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(MemberDO::toDo).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public Long countByContactInfo(String orgId, String value, MemberTypeEnum memberTypeEnum, DeliveryTypeEnum deliveryTypeEnum) {
        String field = "";
        if (deliveryTypeEnum != null) {
            switch (deliveryTypeEnum) {
                case SMS:
                    field = "phone";
                    break;
                case EMAIL:
                    field = "email";
                    break;
                case API:
                    field = memberTypeEnum.getIndex() == 2 ? "employee_id" : "out_no";
                    break;
                default:
                    field = "";
            }
        }
        return memberMapper.countByContactInfo(orgId, value, field, memberTypeEnum.getIndex());
    }

    @Override
    public List<MemberDO> listByContactInfo(String orgId, String value, MemberTypeEnum memberTypeEnum, DeliveryTypeEnum deliveryTypeEnum, int start, int size) {
        String field = "";
        if (deliveryTypeEnum != null) {
            switch (deliveryTypeEnum) {
                case SMS:
                    field = "phone";
                    break;
                case EMAIL:
                    field = "email";
                    break;
                case API:
                    field = memberTypeEnum.getIndex() == 2 ? "employee_id" : "out_no";
                    break;
                default:
                    field = "";
            }
        }
        List<MemberEntity> entities =
                memberMapper.listByContactInfo(orgId, value, field, memberTypeEnum.getIndex(), start, size);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();

    }

    @Override
    public Long countInstituteMembersByContactInfo(String orgId, String value, DeliveryTypeEnum deliveryTypeEnum) {
        String field = "";
        if (deliveryTypeEnum != null) {
            switch (deliveryTypeEnum) {
                case SMS:
                    field = "phone";
                    break;
                case EMAIL:
                    field = "email";
                    break;
                case API:
                    field = "out_no";
                    break;
                default:
                    field = "";
            }
        }
        return memberMapper.countInstituteMembersByContactInfo(orgId, value, field);
    }

    @Override
    public List<MemberDO> listInstituteMembersByContactInfo(String orgId, String value, DeliveryTypeEnum deliveryTypeEnum, int start, int size) {
        String field = "";
        if (deliveryTypeEnum != null) {
            switch (deliveryTypeEnum) {
                case SMS:
                    field = "phone";
                    break;
                case EMAIL:
                    field = "email";
                    break;
                case API:
                    field = "out_no";
                    break;
                default:
                    field = "";
            }
        }
        List<MemberEntity> entities = memberMapper.listInstituteMembersByContactInfo(orgId, value, field, start, size);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public Boolean updateStatusByOrgIdAndAttribute(int status, String orgId, Integer attribute) {
        memberMapper.updateStatusByOrgIdAndAttribute(status, orgId, attribute, DateUtil.getCommonDate());
        return Boolean.TRUE;
    }

    @Override
    public List<MemberDO> filterMembers(FuzzyMemberDynamicSql sql) {
        List<MemberEntity> entities = memberMapper.findByFuzzyMemberDynamicSql(sql, sql.getWrapper());
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public Integer countDeliveryMembers(DeliveryMembersDynamicSql dynamicSql){
        return memberMapper.countDeliveryMembers(dynamicSql, dynamicSql.getWrapper());
    }

    @Override
    public List<MemberDO> listDeliveryMembers(DeliveryMembersDynamicSql dynamicSql){
        List<MemberEntity> memberEntities = memberMapper.listDeliveryMembers(dynamicSql, dynamicSql.getWrapper());
        return memberEntities.stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public List<MemberDO> findByOrgIdAndInstituteNameAndStatusNot(String orgId, String instituteName, Integer status) {
        List<MemberEntity> entities =
                memberMapper.findByOrgIdAndInstituteNameAndStatusNot(orgId, instituteName, status);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public MemberDO findOneByNameAndMtypeAndStatusNe(String name, int mType, int status) {
        MemberEntity entity = memberMapper.findOneByNameAndMtypeAndStatusNe(name, mType, status);
        return MemberDO.toDo(entity);
    }

    @Override
    public List<MemberDO> findByIds(List<String> ids) {
        List<MemberEntity> entities = memberMapper.findByIds(ids);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public MemberDO findByUserId(String orgId, String userId) {
        MemberEntity entity = memberMapper.findByUserId(orgId, userId);
        return MemberDO.toDo(entity);
    }

    @Override
    public List<MemberDO> findByParam(QueryWrapper wrapper) {
        List<MemberEntity> entities = memberMapper.findByWrapper(wrapper);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    /**
     * 批量修改扩展字段名
     */
    @Override
    public void batchUpdateFieldName(String orgId, Integer memberType, List<ExtendFieldDO> extendFieldDOs) {
        if (CollectionUtils.isEmpty(extendFieldDOs)) {
            return;
        }
        List<MemberEntity> existsMembers = memberMapper.findExtendExistsMember(orgId, memberType);
        List<MemberEntity> newMembers = new ArrayList<>();
        for (MemberEntity member : existsMembers) {
            boolean hasCheck = false;
            JSONArray array = JSONArray.parseArray(member.getFieldValList());
            if (array == null) {
                continue;
            }
            for (int i = 0; i < array.size(); i++) {
                JSONObject jb = JSONObject.parseObject(array.getString(i));
                for (ExtendFieldDO itemDO : extendFieldDOs) {
                    if (jb != null && itemDO.getFieldId().equals(jb.getString("field_id"))) {
                        jb.put("field_name", itemDO.getName());
                        hasCheck = true;
                        array.set(i, jb);
                    }
                }
            }
            if (hasCheck) {
                member.setFieldValList(JSONArray.toJSONString(array));
                newMembers.add(member);
            }
        }
        if (!CollectionUtils.isEmpty(newMembers)) {
            memberMapper.updateMemberByField(newMembers);
        }

//        memberMapper.batchUpdateExtendFieldName(orgId, memberType, extendFieldDOs);
    }

    /**
     * 修改扩展字段枚举值
     */
    @Override
    public void updateMemberFieldEnumValue(String orgId, Integer memberType, List<ExtendFieldEnumItemDO> extendFieldEnumItemDOS) {
        if (CollectionUtils.isEmpty(extendFieldEnumItemDOS)) {
            return;
        }
        List<MemberEntity> existsMembers = memberMapper.findExtendExistsMember(orgId, memberType);
        List<MemberEntity> newMembers = new ArrayList<>();
        for (MemberEntity member : existsMembers) {
            boolean hasCheck = false;
            JSONArray array = JSONArray.parseArray(member.getFieldValList());
            if (array == null) {
                continue;
            }
            for (int i = 0; i < array.size(); i++) {
                JSONObject jb = JSONObject.parseObject(array.getString(i));
                for (ExtendFieldEnumItemDO itemDO : extendFieldEnumItemDOS) {
                    if (jb != null && itemDO.getExtendFieldId().equals(jb.getString("field_id")) && itemDO.getFieldEnumId().equals(jb.getString("field_value"))) {
                        jb.put("field_value", itemDO.getName());
                        hasCheck = true;
                        array.set(i, jb);
                    }
                }
            }
            if (hasCheck) {
                member.setFieldValList(JSONArray.toJSONString(array));
                newMembers.add(member);
            }
        }
        if (!CollectionUtils.isEmpty(newMembers)) {
            memberMapper.updateMemberByField(newMembers);
        }
//        memberMapper.batchUpdateExtendFieldValue(orgId, memberType, extendFieldEnumItemDOS);
    }

    /**
     * 批量删除扩展字段
     */
    @Override
    public void batchDeleteExtendFields(@NotNull String orgId, @NotNull Integer memberType, @NotEmpty Collection<String> fieldIds) {
        if (CollectionUtils.isEmpty(fieldIds)) {
            return;
        }
        List<MemberEntity> existsMembers = memberMapper.findExtendExistsMember(orgId, memberType);
        List<MemberEntity> newMembers = new ArrayList<>();
        for (MemberEntity member : existsMembers) {
            boolean hasCheck = false;
            JSONArray array = JSONArray.parseArray(member.getFieldValList());
            if (array == null) {
                continue;
            }
            for (int i = 0; i < array.size(); i++) {
                JSONObject jb = JSONObject.parseObject(array.getString(i));
                if (jb != null && fieldIds.contains(jb.getString("field_id"))) {
                    array.remove(i);
                    hasCheck = true;
                    i--;
                }
            }
            if (hasCheck) {
                member.setFieldValList(JSONArray.toJSONString(array));
                newMembers.add(member);
            }
        }

        if (!CollectionUtils.isEmpty(newMembers)) {
            memberMapper.updateMemberByField(newMembers);
        }
        // memberMapper.batchDeleteExtendField(orgId, memberType, fieldIds);
    }

    @Override
    public void saveLabels(Map<String, List<LabelValueIdParam>> modifiedMemberLabelMap) {
        if (CollUtil.isNotEmpty(modifiedMemberLabelMap)) {
            modifiedMemberLabelMap.forEach((memberId, labels) -> {
                memberMapper.updateMemberLabelById(memberId, JSONObject.toJSONString(labels));
            });
        }
    }

    @Override
    public MemberDO findByOrgIdAndFieldAndAttributeAndStatus(String orgId, String field, String value, Integer memberType, Integer status) {
        MemberEntity entity = memberMapper.findByOrgIdAndFieldAndAttributeAndStatus(orgId, field, value, memberType, status);
        return MemberDO.toDo(entity);
    }

    @Override
    public MemberDO manualSave(MemberDO member) {
        member.setId(StringUtil.getId());
        memberMapper.saveMember(MemberDO.toEntity(member));
        MemberEntity entity = memberMapper.findById(member.getId());
        return MemberDO.toDo(entity);
    }

    @Override
    public MemberDO findById(String id) {
        MemberEntity entity = memberMapper.findById(id);
        return MemberDO.toDo(entity);
    }

    @Override
    public List<MemberDO> listMembersByRegexName(@NotNull String orgId,
                                                 @Nullable Integer memberType,
                                                 @Nullable String regexName,
                                                 @NotNull Integer offset,
                                                 @NotNull Integer size) {
        List<MemberEntity> members = memberMapper.listMembersByRegexName(orgId, memberType, regexName, offset, size);
        return members.stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public Integer countMembersByRegexName(@NotNull String orgId, @Nullable Integer memberType, @Nullable String regexName) {
        return memberMapper.countMembersByRegexName(orgId, memberType, regexName);
    }

    @Override
    public void updateMember(MemberDO member, Boolean supportGroupToken) {
        memberMapper.updateMember(MemberDO.toEntity(member));
    }

    @Override
    public MemberDO importSave(MemberDO member) {
        member.setId(StringUtil.getId());
        memberMapper.saveMember(MemberDO.toEntity(member));
        MemberEntity entity = memberMapper.findById(member.getId());
        return MemberDO.toDo(entity);
    }

    @Override
    public Integer countSlice(String orgId) {
        return memberMapper.countByOrgIAndMemberTypeAndStatusNe(orgId, MemberTypeEnum.INDIVIDUAL.getIndex(), MemberStatusEnum.SOFT_DELETE.getIndex()).intValue();
    }

    @Override
    public List<MemberDO> findSlice(String orgId, String startOffset, int pageSize) {
        List<MemberEntity> entities = memberMapper.findByOrgIdAndAttributeAndStatus(orgId, MemberTypeEnum.INDIVIDUAL.getIndex(), MemberStatusEnum.SOFT_DELETE.getIndex(), startOffset, pageSize);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(MemberDO::toDo).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public MemberDO findLastInSlice(String orgId, String startOffset, int pageSize) {
        MemberEntity entity = memberMapper.findOneByOrgIdAndAttributeAndStatus(orgId, MemberTypeEnum.INDIVIDUAL.getIndex(), MemberStatusEnum.SOFT_DELETE.getIndex(), startOffset, pageSize - 1);
        return MemberDO.toDo(entity);
    }

    @Override
    public MemberDO findByOrgIdAndFieldAndMemberType(String orgId, String field, String value, Integer memberType) {
        if (field.equals("mobile")) {
            field = "phone";
        }
        if (field.equals("employeeID")) {
            field = "employee_id";
        }
        MemberEntity entity = memberMapper.findByOrgIdAndFieldAndMemberType(orgId, field, value, memberType);
        return MemberDO.toDo(entity);
    }

    @Override
    public MemberDO createInnerMemberByCreateUser(MemberDO member) {
        member.setId(StringUtil.getId());
        memberMapper.saveMember(MemberDO.toEntity(member));
        MemberEntity entity = memberMapper.findById(member.getId());
        return MemberDO.toDo(entity);
    }

    @Override
    public Integer countByDynamicSql(SelectMemberDynamicSql queryWrapper) {
        return memberMapper.countByDynamicSql(queryWrapper, queryWrapper.getWrapper());
    }

    @Override
    public List<MemberDO> filterMembersByDynamicSql(SelectMemberDynamicSql dynamicSql) {
        List<MemberEntity> entities = memberMapper.filterMembersByDynamicSql(dynamicSql, dynamicSql.getWrapper());
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public MemberDO surveySaveMember(MemberDO member) {
        member.setId(StringUtil.getId());
        memberMapper.saveMember(MemberDO.toEntity(member));
        MemberEntity entity = memberMapper.findById(member.getId());
        return MemberDO.toDo(entity);
    }

    @Override
    public MemberDO deliverSaveMember(MemberDO member) {
        member.setId(StringUtil.getId());
        memberMapper.saveMember(MemberDO.toEntity(member));
        MemberEntity entity = memberMapper.findById(member.getId());
        return MemberDO.toDo(entity);
    }

    @Override
    public Long countOrgMember(String orgId, Integer memberType) {
        return memberMapper.countByOrgIAndMemberTypeAndStatusAndSourceNe(orgId, memberType, MemberStatusEnum.ACTIVATED.getIndex(), "sample");
    }

    @Override
    public Long countMember(String orgId) {
        return memberMapper.countMember(orgId);
    }

    @Override
    public Long countMember(String orgId, Integer memberType, Integer status) {
        return memberMapper.countByOrgIAndMemberTypeAndStatus(orgId, memberType, status);
    }

    @Override
    public List<MemberDO> findMember(String orgId, int start, Integer batchCount) {
        List<MemberEntity> entities = memberMapper.findMember(orgId, start, batchCount);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public List<MemberDO> findByOrgIdAndStatus(String orgId, int status) {
        List<MemberEntity> entities = memberMapper.findByOrgIdAndStatus(orgId, status);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<MemberDO>();
    }

    @Override
    public void batchSave(List<MemberDO> memberList) {
        if (CollUtil.isNotEmpty(memberList)) {
            List<MemberEntity> memberEntities =
                    memberList.stream().map(MemberDO::toEntity).collect(Collectors.toList());
            memberMapper.batchSave(memberEntities);
        }
    }

    @Override
    public Long countByPeriod(String orgId, int memberType, Date startCreateTime, Date endCreateTime, Date startUpdateTime, Date endUpdateTime) {
        return memberMapper.countByPeriod(orgId, memberType, startCreateTime, endCreateTime, startUpdateTime, endUpdateTime);
    }

    @Override
    public List<MemberDO> listMemberByPeriod(String orgId, int memberType,
                                             Date startCreateTime, Date endCreateTime,
                                             Date startUpdateTime, Date endUpdateTime,
                                             Integer offset, Integer size) {
        List<MemberEntity> entities = memberMapper.listMemberByPeriod(orgId, memberType, startCreateTime, endCreateTime, startUpdateTime, endUpdateTime, offset, size);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public List<MemberDO> findByOrgIdAndMemberTypeAndInstituteNameAndStatusNot(String orgId,
                                                                               int memberType,
                                                                               String instituteName,
                                                                               int status) {
        List<MemberEntity> entities = memberMapper.findByOrgIdAndMemberTypeAndInstituteNameAndStatusNot(orgId, memberType, instituteName, status);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public MemberDO findOneByOrgIdAndMemberTypeAndStatusAndGroupSyncToken(String orgId, int memberType, int status) {
        MemberEntity entity = memberMapper.findOneByOrgIdAndMemberTypeAndStatusAndGroupSyncToken(orgId, memberType, status);
        if (ObjectUtil.isNotEmpty(entity)) {
            return MemberDO.toDo(entity);
        }
        return null;
    }

    @Override
    public MemberDO findOneByIdAndStatus(String memberId, String orgId, int memberType, int status) {
        MemberEntity entity = memberMapper.findOneByIdAndStatus(memberId, orgId, memberType, status);
        if (ObjectUtil.isNotEmpty(entity)) {
            return MemberDO.toDo(entity);
        }
        return null;
    }

    @Override
    public void updateMemberGroupSyncToken(String memberId, String newGroupSyncToken, String oldGroupSyncToken) {
        memberMapper.updateMemberGroupSyncToken(memberId, newGroupSyncToken, oldGroupSyncToken);
    }

    @Override
    public Integer updateMemberGroups(String groups, String memberId, String groupSyncToken) {
        return memberMapper.updateMemberGroups(groups, memberId, groupSyncToken);
    }

    @Override
    public Long countByOrgIdAndMemberTypeAndStatusAndSeq(String orgId, int memberType, int status, Long seq) {
        return memberMapper.countByOrgIdAndMemberTypeAndStatusAndSeq(orgId, memberType, status, seq);
    }

    @Override
    public void deleteGroup(String orgId, int memberType, int status, Long seq, Date startTime, Date endTime) {
        List<MemberEntity> members = memberMapper.findGroupByParam(orgId, memberType, status, seq, startTime, endTime);
        if (CollectionUtils.isEmpty(members)) {
            return;
        }

        List<MemberEntity> newMembers = new ArrayList<>();
        for (MemberEntity member : members) {
            boolean hasCheck = false;
            JSONArray array = JSONArray.parseArray(member.getGroups());
            if (array == null) {
                continue;
            }
            for (int i = 0; i < array.size(); i++) {
                String jb = array.getString(i);
                if (jb != null && jb.equals(String.valueOf(seq))) {
                    hasCheck = true;
                    array.remove(i);
                    i--;
                }

            }
            if (hasCheck) {
                member.setGroups(JSONArray.toJSONString(array));
                newMembers.add(member);
            }
        }
        if (!CollectionUtils.isEmpty(newMembers)) {
            memberMapper.updateGroups(newMembers);
        }

//        memberMapper.deleteGroup(orgId, memberType, status, seq, startTime, endTime);
    }

    @Override
    public MemberDO findOneByOrgIdAndMemberTypeAndStatusAndCreateTime(String orgId, int memberType, int status, Date endTime, long offset, int limit) {
        MemberEntity entity = memberMapper.findOneByOrgIdAndMemberTypeAndStatusAndCreateTime(orgId, memberType, status, endTime, offset, limit);
        if (Objects.nonNull(entity)) {
            return MemberDO.toDo(entity);
        }
        return null;
    }

    @Override
    public Long countByOrgIdAndMemberTypeAndStatusAndCreateTime(String orgId, int memberType, int status, Date currTime) {
        return memberMapper.countByOrgIdAndMemberTypeAndStatusAndCreateTime(orgId, memberType, status, currTime);
    }

    @Override
    public Long countByOrgIdAndMemberTypeAndStatusAndGroupsAndCreateTime(String orgId, int memberType, int status, Long seq, Date currTime) {
        return memberMapper.countByOrgIdAndMemberTypeAndStatusAndGroupsAndCreateTime(orgId, memberType, status, seq, currTime);
    }

    @Override
    public MemberDO findOneByOrgIdAndMemberTypeAndStatusAndGroupsAndCreateTime(String orgId, int memberType, int status, Long seq, Date endTime, long offset, int limit) {
        MemberEntity entity = memberMapper.findOneByOrgIdAndMemberTypeAndStatusAndGroupsAndCreateTime(orgId, memberType, status, seq, endTime, offset, limit);
        if (Objects.nonNull(entity)) {
            return MemberDO.toDo(entity);
        }
        return null;
    }

    @Override
    public Integer updateMembersByDynamicSql(UpdateMemberGroupDynamicSql dynamicSql) {
        return memberMapper.updateByDynamicSql(dynamicSql, dynamicSql.getWrapper());
    }

    @Override
    public List<String> deleteFilterMembers(SelectMemberDynamicSql dynamicSql, int size) {
        dynamicSql.setStart(size);
        // 先查询相关的联系人
        List<MemberEntity> deleteMembers = memberMapper.findDeleteMembers(dynamicSql, dynamicSql.getWrapper());
        Date updateTime = DateUtil.getCommonDate();
        if (CollUtil.isNotEmpty(deleteMembers)) {
            List<String> ids = new ArrayList<>();
            deleteMembers.forEach(item -> {
                item.setStatus(MemberStatusEnum.SOFT_DELETE.getIndex());
                item.setUpdateTime(updateTime);
                ids.add(item.getId());
            });
            // 根据id删除联系人
            memberMapper.deleteByIds(ids, updateTime);
            return  ids;
        }
        return new ArrayList<>();
    }

    @Override
    public MemberDO findOneByOrgIdAndOutNoAndAttributeAndStatus(String orgId, String outNo,
                                                                Integer memberType, int status) {
        MemberEntity entity = memberMapper.findOneByOrgIdAndOutNoAndAttributeAndStatus(orgId, outNo, memberType, status);
        if (Objects.nonNull(entity)) {
            return MemberDO.toDo(entity);
        }
        return null;
    }

    @Override
    public MemberDO findOneByOrgIdAndMemberTypeAndStatusAndAppIdAndOpenId(String orgId, MemberTypeEnum individual, MemberStatusEnum activated, String appId, String openId) {
        MemberEntity entity = memberMapper.findOneByOrgIdAndMemberTypeAndStatusAndAppIdAndOpenId(orgId, individual.getIndex(), activated.getIndex(), appId, openId);
        if (Objects.nonNull(entity)) {
            return MemberDO.toDo(entity);
        }
        return null;
    }

    @Override
    public String wechatSaveMember(MemberDO member) {
        member.setId(StringUtil.getId());
        memberMapper.saveMember(MemberDO.toEntity(member));
        return member.getId();
    }

    @Override
    public List<MemberDO> findByWx(Integer memberType, String orgId, Integer status, List<MemberQuery> queryParams) {
        List<MemberEntity> entities = memberMapper.findByWx(memberType, orgId, status, queryParams);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public List<MemberDO> findByUpdateTimeAfter(String time, int start, int batchCount) {
        List<MemberEntity> entities = memberMapper.findByUpdateTimeAfter(time, start, batchCount);
        if (CollUtil.isNotEmpty(entities)) {
            return entities.stream().map(entity -> MemberDO.toDo(entity)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    /**
     * 预处理condition，包括字段名、参数
     *
     * @param jsonConditionUnit 最小单位condition
     */
    /*private void preprocessingUnitCondition(JSONObject jsonConditionUnit) {
        // 来源
        jsonConditionUnit.put("source", "");
        // 字段名
        String fieldName = jsonConditionUnit.getString("name");

        // 获取前端参数映射到表的列名
        String columnName = MysqlOperatorMapper.memberColumnMapping(fieldName);

        // 特殊字段名
        if ("field_val_list.field_value".equals(columnName)) {
            columnName = String.format("%s -> '$.%s'", "field_val_list", "field_value");
        } else if ("store_id".equals(columnName)) {
            JSONArray values = jsonConditionUnit.getJSONArray("value");
            jsonConditionUnit.put("value", values.getString(values.size() - 1));
        } else if (columnName.startsWith("address")) {
            columnName = String.format("%s -> '$[%s]'", "address", columnName.charAt(columnName.length() - 1));
        }
        jsonConditionUnit.put("name", columnName);
    }*/

    private MemberDO convert(MemberEntity entity) {
        MemberDO res = new MemberDO();
        res.setId(entity.getId());
        res.setOrgId(entity.getOrgId());
        res.setMemberType(entity.getMemberType());
        res.setStatus(entity.getStatus());
        res.setStoreId(entity.getStoreId());
        res.setSource(entity.getSource());
        res.setName(entity.getName());
        res.setEmail(entity.getEmail());
        res.setPhone(entity.getPhone());
        res.setGender(entity.getGender());
        res.setStoreId(entity.getStoreId());
        res.setContent(entity.getContent());
        res.setOpenId(entity.getOpenId());
        res.setAppId(entity.getAppId());
        res.setAliPayUserId(entity.getAliPayUserId());
        res.setMemberNo(entity.getMemberNo());
        res.setAddress(entity.getAddress());
        res.setEmployeeStatus(entity.getEmployeeStatus());
        res.setBirthday(entity.getBirthday());
        res.setDepartment(entity.getDepartment());
        res.setPosition(entity.getPosition());
        res.setInstituteId(entity.getInstituteId());
        res.setInstituteName(entity.getInstituteName());
        res.setUserId(entity.getUserId());
        res.setAge(entity.getAge());
        res.setLabels(entity.getLabels());
        res.setFieldValList(entity.getFieldValList());
        res.setCreateTime(entity.getCreateTime());
        res.setUpdateTime(entity.getUpdateTime());
        res.setNickname(entity.getNickname());
        res.setEmployeeId(entity.getEmployeeId());
        res.setOutNo(entity.getOutNo());
        return res;
    }

    private MemberEntity convert(MemberDO entity) {
        MemberEntity res = new MemberEntity();
        res.setId(entity.getId());
        res.setOrgId(entity.getOrgId());
        res.setMemberType(entity.getMemberType());
        res.setStatus(entity.getStatus());
        res.setStoreId(entity.getStoreId());
        res.setSource(entity.getSource());
        res.setName(entity.getName());
        res.setEmail(entity.getEmail());
        res.setPhone(entity.getPhone());
        res.setGender(entity.getGender());
        res.setStoreId(entity.getStoreId());
        res.setContent(entity.getContent());
        res.setOpenId(entity.getOpenId());
        res.setAppId(entity.getAppId());
        res.setAliPayUserId(entity.getAliPayUserId());
        res.setMemberNo(entity.getMemberNo());
        res.setAddress(entity.getAddress());
        res.setEmployeeStatus(entity.getEmployeeStatus());
        res.setBirthday(entity.getBirthday());
        res.setDepartment(entity.getDepartment());
        res.setPosition(entity.getPosition());
        res.setInstituteId(entity.getInstituteId());
        res.setInstituteName(entity.getInstituteName());
        res.setUserId(entity.getUserId());
        res.setAge(entity.getAge());
        res.setLabels(entity.getLabels());
        res.setFieldValList(entity.getFieldValList());
        res.setCreateTime(entity.getCreateTime());
        res.setUpdateTime(entity.getUpdateTime());
        res.setOutNo(entity.getOutNo());
        res.setAvatar(entity.getAvatar());
        res.setUnionId(entity.getUnionId());
        res.setNickname(entity.getNickname());
        return res;
    }
}
